#include "../Renderer/Shader.h"
#include "../external/external.h"
#include <string.h>
#include <new>

namespace Nitro::Renderer {

Shader CreateShader(const ShaderDescriptor& desc)
{
    Shader shader;

    [[likely]]
    if (desc.sourceType == SourceCode)
    {
        shader.id = glCreateShader(desc.type);
        auto src = desc.source.c_str();
        glShaderSource(shader.id, 1, &src, nullptr);
    }
    else if (desc.sourceType == BinaryCode)
    {
        throw "BinaryCode not supported yet";
    }
    else if (desc.sourceType == SourceFile)
    {
        std::ifstream sourceFile(desc.source);
        if (!sourceFile.is_open())
        {
            return shader;
        }

        std::stringstream sourceBuffer;
        sourceBuffer << sourceFile.rdbuf();
        auto sourceString = sourceBuffer.str();
        auto src = sourceString.c_str();
        shader.id = glCreateShader(desc.type);
        glShaderSource(shader.id, 1, &src, nullptr);
    }
    else
    {
        std::ifstream sourceFile(desc.source, std::ios_base::binary);
        std::stringstream sourceBuffer;
        sourceBuffer << sourceFile.rdbuf();
        auto sourceString = sourceBuffer.str();
        auto src = sourceString.c_str();
        throw;
    }

    glCompileShader(shader.id);
    return shader;
}

bool Shader::hasReport()
{
    if (id == 0) return true;
    int status;
    glGetShaderiv(id, GL_COMPILE_STATUS, &status);
    return !status;
}

std::string Shader::getReport()
{
    if (id == 0) return "Error: Could not open shader file\n";
    char buffer[1024];
    memset(buffer, 0, sizeof(buffer));
    glGetShaderInfoLog(id, 1024, nullptr, buffer);
    return std::move(std::string(buffer));
}

} // namespace Nitro::Renderer